﻿#include "zoomvideowidget.h"
#include <QAction>
#include <QApplication>
#include <QDesktopWidget>
#include <QPainter>
#include <QResizeEvent>
#include <QStyleOption>
#include <QToolBar>
#include "characterset.h"
#include "videowindow.h"

ZoomVideoWidget::ZoomVideoWidget(VideoWindow *parent) : QWidget(parent, Qt::Tool), sourceWidget(parent),
    toolBar(new QToolBar(this)), rotate(0)
{    
    Q_ASSERT(parent);
    setAttribute(Qt::WA_DeleteOnClose);
    setMouseTracking(true);
    setTitle();
    toolBar->hide();
    toolBar->setToolButtonStyle(Qt::ToolButtonTextOnly);
    toolBar->addAction(QLatin1String("x0.5"), this, SLOT(zoomTo()));
    toolBar->addAction(QLatin1String("x1"), this, SLOT(zoomTo()));
    toolBar->addAction(QLatin1String("x2"), this, SLOT(zoomTo()));
    toolBar->addAction(QObject::trECSUTF8("最大化"), this, SLOT(showMaximized()));
    toolBar->addAction(QObject::trECSUTF8("全屏"), this, SLOT(showFullScreen()));
    toolBar->addAction(QObject::trECSUTF8("独立"), this, SLOT(separate()))->setCheckable(true);
    toolBar->addSeparator();
    toolBar->addAction(QObject::trECSUTF8("左转"), this, SLOT(anticlockwiseRotate()));
    toolBar->addAction(QObject::trECSUTF8("复原"), this, SLOT(resetRotate()));
    toolBar->addAction(QObject::trECSUTF8("右转"), this, SLOT(clockwiseRotate()));
    toolBar->setStyleSheet(QLatin1String("QToolBar{background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(170, 170, 255, 128), stop:1 rgba(170, 170, 255, 0));}"));
}

void ZoomVideoWidget::setTitle()
{
    if(sourceWidget->uid > 0)
        setWindowTitle((sourceWidget->uname.isEmpty() ? QString::number(sourceWidget->uid) : sourceWidget->uname));
    else
        setWindowTitle(QObject::trECSUTF8("视频"));
}

void ZoomVideoWidget::setRotate(quint8 rotateValue)
{
    if(rotate == rotateValue)
        return;
    if(rotate%2 != rotateValue%2)
    {
        qreal factor = exactlyFactor();
        rotate = rotateValue;
        if(factor > 0)
            resize(videoSize() * factor);
        else
            adJustVideoRect(this->size());
    }
    else
        rotate = rotateValue;
    update();
}

quint8 ZoomVideoWidget::getRotate()
{
    return rotate;
}

void ZoomVideoWidget::paintEvent(QPaintEvent *e)
{
    const QRect& rt = e->rect();
    if(!videoRect.isNull() && rt.intersects(videoRect))
    {
        QPainter paint(this);
        if(sourceWidget->videoPixmap.isNull())
        {
            //画背景图片
            QStyle *style = sourceWidget->style();
            QStyleOption opt;
            opt.init(sourceWidget);
            if(sourceWidget->uid > 0)
                opt.state |= QStyle::State_On;
            opt.rect = videoRect;
            style->drawPrimitive(QStyle::PE_Widget, &opt, &paint, sourceWidget);
        }
        else
        {
            paint.setRenderHint(QPainter::SmoothPixmapTransform);
            QSize paintSize = videoRect.size();
            QSize pixmapSize = sourceWidget->videoPixmap.size();
            if(rotate % 2 == 1)
                pixmapSize.transpose();
            QRect trueRect;
            if(paintSize == pixmapSize)
            {
                //QRect intersect = rt.intersected(videoRect);
                //paint.drawPixmap(rt, sourceWidget->videoPixmap, QRect(intersect.left() - videoRect.left(), intersect.top() - videoRect.top(), intersect.width(), intersect.height()));
                trueRect = videoRect;
            }
            else
            {
                QSize scaled = pixmapSize.scaled(paintSize, Qt::KeepAspectRatio);
                if(paintSize == scaled)
                    trueRect = videoRect;
                else
                {
                    paint.fillRect(videoRect, Qt::black);
                    trueRect.setRect((videoRect.width() - scaled.width()) / 2 + videoRect.left(), (videoRect.height() - scaled.height()) / 2 + videoRect.top(), scaled.width(), scaled.height());
                }
            }
            QRect paintRect;
            switch (rotate) {
            case 1:
                paint.translate(trueRect.left() + trueRect.width(), trueRect.top());
                paint.rotate(90);
                paintRect.setRect(0, 0, trueRect.height(), trueRect.width());
                break;
            case 2:
                paint.translate(trueRect.left() + trueRect.width(), trueRect.top() + trueRect.height());
                paint.rotate(180);
                paintRect.setRect(0, 0, trueRect.width(), trueRect.height());
                break;
            case 3:
                paint.translate(trueRect.left(), trueRect.top() + trueRect.height());
                paint.rotate(270);
                paintRect.setRect(0, 0, trueRect.height(), trueRect.width());
                break;
            default:
                paint.translate(trueRect.left(), trueRect.top());
                paintRect.setRect(0, 0, trueRect.width(), trueRect.height());
                break;
            }
            paint.drawPixmap(paintRect, sourceWidget->videoPixmap);
        }
    }
}

void ZoomVideoWidget::resizeEvent(QResizeEvent *e)
{
    adJustVideoRect(e->size());
    QWidget::resizeEvent(e);
}

void ZoomVideoWidget::enterEvent(QEvent *e)
{
    toolBar->setVisible(videoRect.contains(((QEnterEvent*)e)->pos()));
    QWidget::enterEvent(e);
}

void ZoomVideoWidget::leaveEvent(QEvent *e)
{
    toolBar->hide();
    QWidget::leaveEvent(e);
}

void ZoomVideoWidget::mouseMoveEvent(QMouseEvent *e)
{
    toolBar->setVisible(videoRect.contains(e->pos()));
    QWidget::mouseMoveEvent(e);
}

void ZoomVideoWidget::mouseDoubleClickEvent(QMouseEvent *e)
{
    close();
}

void ZoomVideoWidget::keyPressEvent(QKeyEvent *e)
{
    if (e->key() == Qt::Key_Escape) {
        e->accept();
        close();
    } else {
        QWidget::keyPressEvent(e);
    }
}

void ZoomVideoWidget::zoomTo()
{
    if(isMaximized() || isFullScreen())
        showNormal();
    qreal factor = 1;
    if(QAction *action = qobject_cast<QAction*>(sender()))
    {
        if(action->text() == "x0.5")
            factor = 0.5;
        else if(action->text() == "x2")
            factor = 2;
    }
    resize(videoSize() * factor);
}

void ZoomVideoWidget::separate()
{
    if(QAction *action = qobject_cast<QAction*>(sender()))
    {
        if(action->isChecked())
        {
            //独立
            if(this->parent())
            {
                this->setParent(0);
                this->show();
                connect(sourceWidget, &QObject::destroyed, this, &ZoomVideoWidget::close, Qt::UniqueConnection);
            }
        }
        else if(this->parent() == Q_NULLPTR)
        {
            //恢复
            disconnect(sourceWidget, &QObject::destroyed, this, &ZoomVideoWidget::close);
            this->setParent(sourceWidget);
            this->setWindowFlags(Qt::Tool);
            this->showNormal();
        }
    }
}

void ZoomVideoWidget::clockwiseRotate()
{
    setRotate((rotate + 1) % 4);
}

void ZoomVideoWidget::anticlockwiseRotate()
{
    setRotate((rotate + 3) % 4);
}

void ZoomVideoWidget::resetRotate()
{
    setRotate(0);
}

void ZoomVideoWidget::adJustVideoRect(const QSize &totalSize)
{
    QRect rect(QPoint(), videoSize().scaled(totalSize, Qt::KeepAspectRatio));
    rect.moveCenter(QPoint((totalSize.width() - 1) / 2, (totalSize.height() - 1) / 2));
    videoRect = rect;
    rect.setHeight(toolBar->sizeHint().height());
    toolBar->setGeometry(rect);
}

QSize ZoomVideoWidget::videoSize()
{
    return rotate % 2 == 0 ? sourceWidget->videoSize : sourceWidget->videoSize.transposed();
}

qreal ZoomVideoWidget::exactlyFactor()
{
    if(isMaximized() || isFullScreen())
        return 0;
    QSize videoSize = this->videoSize();
    if(videoSize.isEmpty())
        return 0;
    QSize currentSize = this->size();
    qreal factor = qreal(currentSize.width()) / videoSize.width();
    if(qreal(currentSize.height()) / videoSize.height() == factor)
        return factor;
    return 0;
}
